/*
	system_bakery_lock.c

	Utilises Lamport's Bakery Algorithm to provide a mutual exclusion mechanism for kernel resources.
	The entry/exit functions in this source are for use within the kernel itself, where IRQs are disabled to prevent preemption.

	Author: Aidan Goddard 30/7/13
*/

#include"headers/scheduler_tables.h"
#include"../setup/headers/types.h"
#include"headers/bakery_lock.h"

// entering function
int BakeryEnter(SCH_CLS *lock, int CPUID)
{
	// local variables
	int max_value = 0;
	int i;

	// set the choosing variable to true whilst picking out the next ticket number
	lock->entering[CPUID] = 1;

	for(i = 0; i < 32; i++)
	{
		if(max_value < lock->ticket[i])
			max_value = lock->ticket[i];
	}
	lock->ticket[CPUID] = max_value + 1;

	// set the choosing variable to false
	lock->entering[CPUID] = 0;

	// now wait until it's this CPU's turn to enter
	for(i = 0; i < 32; i++)
	{
		if(i != CPUID)
		{
			while(lock->entering[i] == 1) {}	// wait while the questioned CPU is still choosing a ticket number
			while((lock->ticket[i] != 0) && ((lock->ticket[CPUID] > lock->ticket[i]) || ((lock->ticket[CPUID] == lock->ticket[i]) && (CPUID > i)))) {}
		}
	}

	// now this CPU may enter the critical region
	// return the ticket number for debugging
	return lock->ticket[CPUID];
}

// leaving function
int BakeryLeave(SCH_CLS *lock, int CPUID)
{
	lock->ticket[CPUID] = 0;
}
